﻿#include "WRWorkTcpCommServerSession.h"
#include "WRWorkTcpCommServerObject.h"
#include "WRWorkTcpCommServerSocket.h"
#include "../WRWorkTcpCommConsts.h"
#include "../WRWorkTcpCommPulsePacket.h"

#include <QList>
#include <QTextCodec>
#include <QByteArray>

//初始化TCP服务会话。
WRWorkTcpCommServerSession::WRWorkTcpCommServerSession(WRWorkTcpCommServerSocket* socket)
    : m_refCnt(1)
{
    m_socket = socket;

    WRWorkTcpCommServer* server = static_cast<WRWorkTcpCommServer*>(socket->parent());
    const WRArray<WRWorkTcpCommServerObjRef*>& objects = server->objects();
    m_objects = WRArray<WRWorkTcpCommServerObject*>(objects.count());
    for(WRu i = 0, l = m_objects.count(); i < l; ++i)
    {
        m_objects[i] = new WRWorkTcpCommServerObject(this, objects[i]);
    }
}

//释放当前对象所占用的相关资源。
WRWorkTcpCommServerSession::~WRWorkTcpCommServerSession()
{
    for(WRu i = 0, l = m_objects.count(); i < l; ++i)
    {
        WRWorkTcpCommServerObject* entry = m_objects[i];
        delete entry;
    }
}

//发送打开结果第一包数据。
void WRWorkTcpCommServerSession::sendOpenResult(WR64s ticks, const QList<WRType*>& types)
{
    int fillLen = 0;
    {
        int remain = types.count() % 8;
        if (remain > 0) fillLen = 8 - remain;
    }
    int cmdLen = 32 + types.count() + fillLen;
    for(int i = 0, l = types.count(); i < l; ++i)
    {
        cmdLen += types[i]->toBytes(0) * sizeof(QUuid);
    }
    WRDataPacket* packet = WRDataPacket::create(cmdLen);
    {
        char* p;
        packet->buffer(&p);

        WRBytes::write((WR32u)WRWorkTcpComm::FrameHeader, p);//帧头
        p += 4;
        WRBytes::write((WR32s)(cmdLen), p);//帧长度
        p += 4;
        WRBytes::write((WR16u)(0xFFFF), p);//全局指令
        p += 2;
        WRBytes::write((WR16u)WRWorkTcpComm::Start, p);//类型
        p += 2;
        WRBytes::write((WR16u)(1), p);//第一包
        p += 2;
        WRBytes::write((WR16u)types.count(), p);//工作类型数量
        p += 2;
        WRBytes::write((WR64s)(ticks), p);//时间戳
        p += 8;

        unsigned char* pLen = (unsigned char*)(p);
        unsigned char* pDat = (unsigned char*)(p + types.count() + fillLen);
        for(int i = 0, l = types.count(); i < l; ++i)
        {
            *pLen = types[i]->toBytes(pDat);
            pDat += *pLen * sizeof(QUuid);
            ++pLen;
        }
        p = (char*)pDat;

        WRBytes::write((WR32u)WRWorkTcpComm::FrameVersion, p);//版本
        p += 4;
        WRBytes::write((WR32u)WRWorkTcpComm::FrameTailor, p);//帧尾
    }
    if (!sendData(packet))
    {
        packet->release();
    }
}
//发送打开结果第二包数据。
void WRWorkTcpCommServerSession::sendOpenResult(WR64s ticks, const WRArray<WRWorkTcpCommServerObject*>& objects)
{
    QByteArray* m_texts = new QByteArray[objects.count() * 2];
    QTextCodec* codec = QTextCodec::codecForName("UTF-8");
    for(WRu i = 0, l = objects.count(); i < l; ++i)
    {
        WRWorkObject* object = objects[i]->target()->value();
        m_texts[i * 2] = codec->fromUnicode(object->title());
        m_texts[i * 2 + 1] = codec->fromUnicode(object->description());
    }
    int dataLen = 16 + 40 * (int)objects.count(); //40=类型标识+唯一标识+父类对象索引+子类对象数量+名称长度+描述长度
    for(WRu i = 0, l = objects.count() * 2; i < l; ++i)
    {
        dataLen += m_texts[i].length();
    }
    int fillLen = 0;
    {
        int remain = dataLen % 8;
        if (remain > 0) fillLen = 8 - remain;
    }
    int cmdLen = 16 + dataLen + fillLen;
    WRDataPacket* packet = WRDataPacket::create(cmdLen);
    {
        char* p;
        packet->buffer(&p);

        WRBytes::write((WR32u)WRWorkTcpComm::FrameHeader, p);//帧头
        p += 4;
        WRBytes::write((WR32s)(cmdLen), p);//帧长度
        p += 4;
        WRBytes::write((WR16u)(0xFFFF), p);//全局指令
        p += 2;
        WRBytes::write((WR16u)WRWorkTcpComm::Start, p);//类型
        p += 2;
        WRBytes::write((WR16u)(2), p);//第二包
        p += 2;
        WRBytes::write((WR16u)(objects.count()), p);//工作类型数量
        p += 2;
        WRBytes::write((WR64s)(ticks), p);//时间戳
        p += 8;

        QUuid* pUuid = (QUuid*)p;//工作对象类型和标识
        WR16u* pIdxCnt = (WR16u*)(p + 32 * objects.count());//父类对象索引和子类对象数量
        for(WRu i = 0, l = objects.count(); i < l; ++i)
        {
            WRWorkTcpCommServerObjRef* objRef = objects[i]->target();
            WRWorkObject* object = objRef->value();

            WRBytes::write((QUuid)(object->type()->uuid()), pUuid);
            ++pUuid;
            WRBytes::write((QUuid)(object->uuid()), pUuid);
            ++pUuid;

            if (objRef->parent() != nullptr)
            {
                WRBytes::write((WR16u)(objRef->parent()->index()), pIdxCnt);
            }
            else
            {
                WRBytes::write((WR16u)0xFFFF, pIdxCnt);
            }
            ++pIdxCnt;
            WRBytes::write((WR16u)(objRef->value()->children().count()), pIdxCnt);
            ++pIdxCnt;
        }
        p = (char*)pIdxCnt;

        WR16u* pLen = (WR16u*)p;
        p += 4 * objects.count();
        for(WRu i = 0, l = objects.count() * 2; i < l; ++i)
        {
            const QByteArray& text = m_texts[i];
            WRBytes::write((WR16u)(text.length()), pLen);
            if (text.length() > 0)
            {
                memcpy(p, text.constData(), text.length());
                p += text.length();
            }
            ++pLen;
        }
        p += fillLen;

        WRBytes::write((WR32u)WRWorkTcpComm::FrameVersion, p);//版本
        p += 4;
    }
    if (!sendData(packet))
    {
        packet->release();
    }
}

//关闭会话。
void WRWorkTcpCommServerSession::shutdown(void)
{
    m_mutex.lock();
    m_socket = 0;
    m_mutex.unlock();
    for(WRu i = 0, l = m_objects.count(); i < l; ++i)
    {
        m_objects[i]->shutdown();
    }
}

//执行接收到的数据帧处理。
void WRWorkTcpCommServerSession::procData(const char* buf, int len)
{
    WR16u index = WRBytes::read<WR16u>(buf);
    buf += 2;
    len -= 2;
    if (index == 0xFFFF) //全局命令
    {
        WR16u cmdType = WRBytes::read<WR16u>(buf);
        buf += 2;
        len -= 2;
        switch(cmdType)
        {
        case WRWorkTcpComm::Start://打开
        {
            WR64s ticks = WRBytes::read<WR64s>(buf + 4);
            WRWorkTcpCommServer* owner = (WRWorkTcpCommServer*)(m_socket->parent());
            if (owner->timestamp().ticks() == ticks)
            {
                WRDataPacket* packet = WRDataPacket::allocate<32>();
                {
                    char* p;
                    packet->buffer(&p);

                    WRBytes::write((WR32u)WRWorkTcpComm::FrameHeader, p);//帧头
                    WRBytes::write((WR32s)(32), p + 4);//帧长度
                    WRBytes::write((WR16u)(0xFFFF), p + 8);//全局指令
                    WRBytes::write((WR16u)WRWorkTcpComm::Start, p + 10);//类型
                    WRBytes::write((WR16u)(1), p + 12);//第一包
                    WRBytes::write((WR16u)(0), p + 14);//工作类型数量
                    WRBytes::write((WR64s)(ticks), p + 16);//时间戳
                    WRBytes::write((WR32u)WRWorkTcpComm::FrameVersion, p + 24);//版本
                    WRBytes::write((WR32u)WRWorkTcpComm::FrameTailor, p + 28);//帧尾
                }
                if (!sendData(packet))
                {
                    packet->release();
                }
            }
            else
            {
                QList<WRType*> types;
                for(WRu i = 0, l = m_objects.count(); i < l; ++i)
                {
                    WRType* type = m_objects[i]->target()->value()->type();
                    if (!types.contains(type))
                    {
                        types.append(type);
                    }
                }
                ticks = owner->timestamp().ticks();
                sendOpenResult(ticks, types);
                sendOpenResult(ticks, m_objects);
            }
        }
            break;
        case WRWorkTcpComm::Close://关闭
            m_socket->close();
            break;
        case WRWorkTcpComm::Pulse://心跳
            WRDataPacket* pulsePacket = WRWorkTcpComm::pulsePacket();
            if (!sendData(pulsePacket))
            {
                pulsePacket->release();
            }
            break;
        }
    }
    else if (index < m_objects.count())
    {
        m_objects[index]->procData((const unsigned char*)buf, len);
    }
}
//执行数据发送操作。
bool WRWorkTcpCommServerSession::sendData(WRDataPacket* packet)
{
    QMutexLocker lck(&m_mutex);
    if (m_socket)
    {
        return m_socket->process(packet);
    }
    return false;
}
